// eztrade-server/src/handler/jsonrpc.rs

use salvo::prelude::*;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};

// 定义 JSON-RPC 请求结构体
#[derive(Debug, Deserialize)]
pub struct JsonRpcRequest {
    pub jsonrpc: String,
    pub method: String,
    pub params: Value,
    pub id: Option<Value>,
}

// 定义 JSON-RPC 响应结构体
#[derive(Debug, Serialize)]
pub struct JsonRpcResponse {
    pub jsonrpc: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub result: Option<Value>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub error: Option<JsonRpcError>,
    pub id: Option<Value>,
}

// 定义 JSON-RPC 错误结构体
#[derive(Debug, Serialize)]
pub struct JsonRpcError {
    pub code: i64,
    pub message: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub data: Option<Value>,
}

// JSON-RPC 处理函数
#[handler]
pub async fn jsonrpc_handler(req: &mut Request, res: &mut Response) {
    // 尝试从请求体中解析 JSON-RPC 请求
    let request_body = match req.parse_json::<JsonRpcRequest>().await {
        Ok(body) => {
            tracing::info!("收到 JSON-RPC 请求: {:?}", body);
            body
        },
        Err(e) => {
            // 如果解析失败，返回 JSON-RPC 解析错误
            tracing::error!("解析 JSON-RPC 请求失败: {:?}", e);
            let error_response = JsonRpcResponse {
                jsonrpc: "2.0".to_string(),
                result: None,
                error: Some(JsonRpcError {
                    code: -32700, // Parse error
                    message: "Parse error".to_string(),
                    data: None,
                }),
                id: None,
            };
            res.status_code(StatusCode::BAD_REQUEST);
            res.render(Json(error_response));
            return;
        }
    };

    // 检查 JSON-RPC 版本
    if request_body.jsonrpc != "2.0" {
        tracing::warn!("JSON-RPC 版本不匹配: {:?}", request_body.jsonrpc);
        let error_response = JsonRpcResponse {
            jsonrpc: "2.0".to_string(),
            result: None,
            error: Some(JsonRpcError {
                code: -32600, // Invalid Request
                message: "Invalid Request: jsonrpc field must be '2.0'".to_string(),
                data: None,
            }),
            id: request_body.id,
        };
        res.status_code(StatusCode::BAD_REQUEST);
        res.render(Json(error_response));
        return;
    }

    // 根据方法名分发请求
    tracing::info!("处理方法: {}", request_body.method);
    match request_body.method.as_str() {
        "add" => {
            // 处理 "add" 方法
            let params = request_body.params;
            let id = request_body.id;
            tracing::debug!("'add' 方法参数: {:?}", params);

            // 尝试从参数中获取两个数字
            let (a, b) = match (params.get(0), params.get(1)) {
                (Some(Value::Number(a)), Some(Value::Number(b))) => {
                    let a_val = a.as_i64().unwrap_or_default();
                    let b_val = b.as_i64().unwrap_or_default();
                    tracing::debug!("解析参数成功: a={}, b={}", a_val, b_val);
                    (a_val, b_val)
                },
                _ => {
                    // 参数类型错误
                    tracing::error!("'add' 方法参数类型错误: {:?}", params);
                    let error_response = JsonRpcResponse {
                        jsonrpc: "2.0".to_string(),
                        result: None,
                        error: Some(JsonRpcError {
                            code: -32602, // Invalid params
                            message: "Invalid params: 'add' method requires two numbers".to_string(),
                            data: None,
                        }),
                        id,
                    };
                    res.status_code(StatusCode::BAD_REQUEST);
                    res.render(Json(error_response));
                    return;
                }
            };

            // 执行加法操作
            let sum = a + b;
            tracing::info!("执行加法操作: {} + {} = {}", a, b, sum);

            // 返回成功响应
            let success_response = JsonRpcResponse {
                jsonrpc: "2.0".to_string(),
                result: Some(json!(sum)),
                error: None,
                id,
            };
            tracing::info!("返回成功响应: {:?}", success_response);
            res.render(Json(success_response));
        },
        _ => {
            // 方法未找到
            tracing::warn!("方法未找到: {}", request_body.method);
            let error_response = JsonRpcResponse {
                jsonrpc: "2.0".to_string(),
                result: None,
                error: Some(JsonRpcError {
                    code: -32601, // Method not found
                    message: format!("Method not found: {}", request_body.method),
                    data: None,
                }),
                id: request_body.id,
            };
            res.status_code(StatusCode::NOT_FOUND);
            res.render(Json(error_response));
        }
    }
}